﻿using System;
using System.Linq;
using System.Collections.Generic;
using CobraCms.Core.Content;
using CobraCms.Core.Content.Interfaces;
using ContentNode = CobraCms.Core.Content.ContentNode;
using ContentNodeData = CobraCms.MsSqlContentRepository.Data.ContentNode;
using CobraCms.Core.Enums;
using CobraCms.MsSqlContentRepository.Data;

namespace CobraCms.MsSqlContentRepository
{
    public class ContentRepository : IContentRepository
    {
        #region Implementation of IContentRepository

        public ContentNode GetContentNode(string nodeId)
        {
            using (var repo = new CobraCmsEntities())
            {
                var query = from c in repo.ContentNodes where c.Id == nodeId select c;
                var data = query.FirstOrDefault();
                if (data == null)
                    return null;

                return data.Converter.ToEntity();
            }
        }

        public void DeleteContentNode(string nodeId)
        {
            using (var repo = new CobraCmsEntities())
            {
                var query = from c in repo.ContentNodes where c.Id == nodeId select c;
                var data = query.FirstOrDefault();
                if (data == null)
                    return;

                repo.DeleteObject(data);
                repo.SaveChanges();
            }
        }

        public ContentNode SaveContentNode(ContentNode node)
        {
            if (String.IsNullOrWhiteSpace(node.Id))
            {
                node.Id = Guid.NewGuid().ToString();
            }
            using (var repo = new CobraCmsEntities())
            {
                var parent = repo.ContentNodes.FirstOrDefault(n => n.Id == node.ParentId);
                var query = from c in repo.ContentNodes where c.Id == node.Id select c;
                var data = query.FirstOrDefault();
                if (data == null)
                {
                    data = new ContentNodeData();
                    repo.AddToContentNodes(data);
                }                
                data.TreeLevel = parent == null ? (short) 1 : (short) (parent.TreeLevel+1);
                data.TreeState = parent == null ?  (short)TreeNodeState.Ok : parent.TreeState;

                data.Converter.FromEntity(node);
                repo.SaveChanges();
                data.Converter.ToEntity(node);
                return node;
            };            
        }

        public List<ContentNode> SearchContentNodes(ContentNodeSearchCriteira searchCriteria)
        {
            using (var repo = new CobraCmsEntities())
            {
                var query = from c in repo.ContentNodes select c;
                if (searchCriteria != null)
                {
                    if (searchCriteria.IsRootNode)
                    {
                        query = from c in query where c.ParentId == null select c;
                    }
                    if (!String.IsNullOrWhiteSpace(searchCriteria.ParentNodeId))
                    {
                        query = from c in query where c.ParentId == searchCriteria.ParentNodeId select c;
                    }

                    if (!String.IsNullOrWhiteSpace(searchCriteria.AncestorNodeId))
                    {
                        query = from c in query
                                join ca in repo.ContentNodeAncestors on c.Id equals ca.AncestorNodeId
                                where ca.ContentNodeId == searchCriteria.AncestorNodeId
                                select c;
                    }
                }
                var data = query.ToList();
                return data.Select(d => d.Converter.ToEntity()).ToList();
            }
        }

        public void ClearRepository()
        {
            using (var repo = new CobraCmsEntities())
            {
                repo.ExecuteStoreCommand("truncate table ContentNodeAncestor");
                repo.ExecuteStoreCommand("truncate table ContentNode");
            }
        }

        #endregion
    }
}
